package edu.zju.gis.cky.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import edu.zju.gis.cky.cons.Constant;
import edu.zju.gis.cky.dao.FlowGeomMapper;
import edu.zju.gis.cky.dao.MetaMapper;
import edu.zju.gis.cky.entity.Meta;
import edu.zju.gis.cky.entity.dto.FlowDetailDTO;
import edu.zju.gis.cky.entity.dto.FlowExtentDTO;
import edu.zju.gis.cky.entity.dto.FlowMatrixDTO;
import edu.zju.gis.cky.entity.po.FlowGeomPO;
import edu.zju.gis.cky.service.LandFlowService;
import org.geotools.data.DataUtilities;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.geojson.feature.FeatureJSON;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKTReader;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.StringWriter;
import java.util.*;

/**
 * @author jiarui
 * @version 1.0, 2022-01-10
 */
@Service
public class LandFlowServieImpl implements LandFlowService {

    @Autowired
    private MetaMapper metaMapper;
    @Autowired
    private FlowGeomMapper geomMapper;

    @Override
    public String[][] getTable(FlowMatrixDTO flowMatrixDTO) {
        Meta metaBegin = metaMapper.selectByPrimaryKey(flowMatrixDTO.getBeginMetaId());
        Meta metaEnd = metaMapper.selectByPrimaryKey(flowMatrixDTO.getEndMetaId());
        String tableName = Constant.MODEL_SCHEMA + ".geom_" + metaBegin.getPgStorage() + "_" + metaEnd.getPgStorage();
        //对行政区划进行处理，例如输入330106000可以查询到330106xxx开始的任意结果
        String xzqh = null;
        int xzqhIndex = 0;
        if (flowMatrixDTO.getXzqh() != null) {
            xzqh = flowMatrixDTO.getXzqh();
            xzqhIndex = xzqh.length();
            for (int i = 0; i < xzqh.length(); i++) {
                if (xzqh.charAt(xzqh.length() - i - 1) != '0') {
                    xzqhIndex = xzqhIndex - i;
                    xzqh = xzqh.substring(0, xzqhIndex);
                    break;
                }
            }
        }
        List<String> fromList = null;
        List<String> toList = null;
        if (flowMatrixDTO.getFrom() != null) {
            fromList = Arrays.asList(flowMatrixDTO.getFrom().split(","));
        }
        if (flowMatrixDTO.getTo() != null) {
            toList = Arrays.asList(flowMatrixDTO.getTo().split(","));
        }
//        List<FlowStatPO> statPOS = geomMapper.getTable(tableName, xzqh, fromList, toList, xzqhIndex);
        List<FlowGeomPO> geomPOS = geomMapper.getDetailSelective(tableName, fromList, toList, xzqh, xzqhIndex);
        //建立编码和名称之间的对应关系
        HashMap<String, String> mapDlbm2dlmc = new HashMap<>();
        Set<String> setFrom = new HashSet<>();
        Set<String> setTo = new HashSet<>();
        for (FlowGeomPO geomPO : geomPOS) {
            mapDlbm2dlmc.put(geomPO.getDlbmFrom(), geomPO.getDlmcFrom());
            mapDlbm2dlmc.put(geomPO.getDlbmTo(), geomPO.getDlmcTo());
            setFrom.add(geomPO.getDlbmFrom());
            setTo.add(geomPO.getDlbmTo());
        }
        setFrom.addAll(setTo);
        List<String> maxList = new ArrayList<>(setFrom);

        //构建double类型的矩阵
        Double[][] matrixDouble = new Double[maxList.size()][maxList.size()];
        for (int i = 0; i < maxList.size(); i++) {
            for (int j = 0; j < maxList.size(); j++) {
                matrixDouble[i][j] = 0.0;
            }
        }
        //开始读取查询的结果，并构建矩阵
        //读取的应该是geomPOS，然后累加计算
        for (FlowGeomPO flowGeomPO : geomPOS) {
            String dlbmFrom = flowGeomPO.getDlbmFrom();
            String dlbmTo = flowGeomPO.getDlbmTo();
            int row = maxList.indexOf(dlbmFrom);
            int col = maxList.indexOf(dlbmTo);
            matrixDouble[col][row] = Double.valueOf(flowGeomPO.getArea()) + matrixDouble[col][row];
        }
        //转成完整的带表头的矩阵
        String[][] matrix = new String[maxList.size() + 2][maxList.size() + 2];
        matrix[0][0] = flowMatrixDTO.getBeginMetaId() + "/" + flowMatrixDTO.getEndMetaId();
        matrix[0][1] = "From";
        matrix[1][0] = "To";
        for (int i = 0; i < maxList.size(); i++) {
            matrix[0][i + 2] = maxList.get(i);
            matrix[1][i + 2] = mapDlbm2dlmc.get(maxList.get(i));
            matrix[i + 2][0] = maxList.get(i);
            matrix[i + 2][1] = mapDlbm2dlmc.get(maxList.get(i));
            for (int j = 0; j < maxList.size(); j++) {
                matrix[i + 2][j + 2] = String.valueOf(matrixDouble[i][j]);
            }
        }
        return matrix;
    }

    @Override
    public PageInfo<JSONObject> getDetail(FlowDetailDTO flowDetailDTO, int pageNum, int pageSize) throws ParseException, IOException {
        Meta metaBegin = metaMapper.selectByPrimaryKey(flowDetailDTO.getBeginMetaId());
        Meta metaEnd = metaMapper.selectByPrimaryKey(flowDetailDTO.getEndMetaId());
        String tableName = Constant.MODEL_SCHEMA + ".geom_" + metaBegin.getPgStorage() + "_" + metaEnd.getPgStorage();
        //对行政区划进行处理，例如输入330106000可以查询到330106xxx开始的任意结果
        String xzqh = null;
        int xzqhIndex = 0;
        if (flowDetailDTO.getXzqh() != null) {
            xzqh = flowDetailDTO.getXzqh();
            xzqhIndex = xzqh.length();
            for (int i = 0; i < xzqh.length(); i++) {
                if (xzqh.charAt(xzqh.length() - i - 1) != '0') {
                    xzqhIndex = xzqhIndex - i;
                    xzqh = xzqh.substring(0, xzqhIndex);
                    break;
                }
            }
        }
        List<String> fromList = null;
        List<String> toList = null;
        if (flowDetailDTO.getFrom() != null) {
            fromList = Arrays.asList(flowDetailDTO.getFrom().split(","));
        }
        if (flowDetailDTO.getTo() != null) {
            toList = Arrays.asList(flowDetailDTO.getTo().split(","));
        }
        PageHelper.startPage(pageNum, pageSize);
        List<FlowGeomPO> detailSelective = geomMapper.getDetailSelective(tableName, fromList, toList, xzqh, xzqhIndex);
        return new PageInfo<>(transPO2GeoJson(detailSelective));
    }

    @Override
    public PageInfo<JSONObject> getListByExtent(FlowExtentDTO flowExtentDTO, int pageNum, int pageSize) {
        Meta metaBegin = metaMapper.selectByPrimaryKey(flowExtentDTO.getBeginData());
        Meta metaEnd = metaMapper.selectByPrimaryKey(flowExtentDTO.getEndData());
        String tableName = Constant.MODEL_SCHEMA + ".geom_" + metaBegin.getPgStorage() + "_" + metaEnd.getPgStorage();
        PageHelper.startPage(pageNum, pageSize);
        List<String> fromList = null;
        List<String> toList = null;
        if (flowExtentDTO.getFrom() != null) {
            fromList = Arrays.asList(flowExtentDTO.getFrom().split(","));
        }
        if (flowExtentDTO.getTo() != null) {
            toList = Arrays.asList(flowExtentDTO.getTo().split(","));
        }
        List<FlowGeomPO> detailSelective = geomMapper.getListByExtent(tableName, fromList, toList, flowExtentDTO.getExtent());
        return new PageInfo<>(transPO2GeoJson(detailSelective));
    }


    private List<JSONObject> transPO2GeoJson(List<FlowGeomPO> detailSelective) {
        List<JSONObject> result = new ArrayList<>();
        for (FlowGeomPO flowGeomPO : detailSelective) {
            String wkt = flowGeomPO.getWKT();
            WKTReader reader = new WKTReader();
            try {
                Geometry geometry = reader.read(wkt);
                String typeSpec = "geometry:" + geometry.getGeometryType() + "," + flowGeomPO.getTypeSpec();
                SimpleFeatureType type = DataUtilities.createType("geom", typeSpec);
                SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(type);
                featureBuilder.set("dlbmFrom", flowGeomPO.getDlbmFrom());
                featureBuilder.set("dlbmTo", flowGeomPO.getDlbmTo());
                featureBuilder.set("dlmcFrom", flowGeomPO.getDlmcFrom());
                featureBuilder.set("dlmcTo", flowGeomPO.getDlmcTo());
                featureBuilder.set("xzqhFrom", flowGeomPO.getXzqhFrom());
                featureBuilder.set("xzqhTo", flowGeomPO.getXzqhTo());
                featureBuilder.set("area", flowGeomPO.getArea());
                featureBuilder.add(geometry);
                SimpleFeature feature = featureBuilder.buildFeature(null);
                StringWriter writer = new StringWriter();
                FeatureJSON fJson = new FeatureJSON();
                fJson.writeFeature(feature, writer);
                String geoJsonResult = writer.toString();
                JSONObject jsonObject = JSONObject.parseObject(geoJsonResult);
                result.add(jsonObject);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }
}
